package gameengine.map;

import java.util.Stack;

import util.Logger;
import enumm.DIRECTION;
import gameengine.map.Path.Node;
import gameengine.map.unit.Unit;

public final class Move extends java.lang.Thread implements Action {
    private transient int xStart;
    private transient int yStart;
    private transient int xTarget;
    private transient int yTarget;
    private transient Map map;
    private final transient int party;
    public static final long DURATION = 200;

    public Move(final int xStartParam, final int yStartParam, final int xTargetParam, final int yTargetParam, final int partyParam) {
        super();
        this.xStart = xStartParam;
        this.yStart = yStartParam;

        this.xTarget = xTargetParam;
        this.yTarget = yTargetParam;
        this.party = partyParam;
    }

    public String serialize() {
        return "MOVE " + this.xStart + " " + this.yStart + " " + this.xTarget + " " + this.yTarget;
    }

    public boolean runAction() {
        super.start();
        return true;
    }

    private Point move(final int xMovePoints, final int yMovePoints, final Point start, final DIRECTION dir) {
        int x = start.getX();
        int y = start.getY();

        final Field startField = this.map.getField(x, y);
        final Unit movedUnit = startField.getUnit();

        pause(DURATION);
        startField.setUnit(null);
        movedUnit.setDir(dir);

        x += xMovePoints;
        y += yMovePoints;

        this.map.getField(x, y).setUnit(movedUnit);

        return new Point(x, y);
    }

    public void pause(final long mili) {
        try {
            Thread.sleep(mili);
        } catch (final InterruptedException e) {
            Logger.d("Move.pause()", e.getMessage());
        }
    }

    @Override
    public void run() {
        final Unit movedUnit = this.map.getField(this.xStart, this.yStart).getUnit();
        final Path path = new Path(this.xStart, this.yStart, this.map);
        final Stack<Node> pathOrders = path.getPath(this.xTarget, this.yTarget);
        final int distance = pathOrders.size();

        Point start = new Point(this.xStart, this.yStart);

        this.map.setReady(false);

        while (!pathOrders.empty()) {
            final Node nextStep = pathOrders.pop();
            switch (nextStep.getDirection()) {
            case N:
                start = move(0, -1, start, nextStep.getDirection());
                break;
            case S:
                start = move(0, 1, start, nextStep.getDirection());
                break;
            case W:
                start = move(-1, 0, start, nextStep.getDirection());
                break;
            case E:
                start = move(1, 0, start, nextStep.getDirection());
                break;
            default:
            }
        }

        movedUnit.hasMoved(distance);
        this.map.moveMent();
        this.map.setReady(true);
    }

    public boolean runAction(final Map mapParam) {
        this.map = mapParam;
        System.out.println(this.map);
        super.start();
        return true;
    }

    public int getParty() {
        return this.party;
    }
}
